﻿namespace Moly.Com
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Xml.Serialization;

    [Serializable]
    public class BuildVersion
    {
        public BuildVersion()
        {
        }

        [XmlElement]
        public string DontUseThis_WhatAHack_serialization_work_around
        {
            get { return ToString(); }
            set
            {
                var sp = value.Split('.');
                Major = int.Parse(sp[0]);
                Minor = int.Parse(sp[1]);
            }
        }

        public string Display
        {
            get { return string.Format("{0}.{1}", Major, Minor); }
        }

        public int Major { get; private set; }

        public int Minor { get; private set; }

        public BuildVersion(string raw, bool hex)
        {
            var spl = raw.Split('.');
            var bs = hex ? 16 : 10;

            if(spl.Length != 2)
            {
                throw new Exception("Invalid version specification[hex.hex]: " + hex);
            }
            Major = Convert.ToInt32(spl[0], bs);
            Minor = Convert.ToInt32(spl[1], bs);
        }

        public BuildVersion(int versionMajor, int versionMinor)
        {
            Major = versionMajor;
            Minor = versionMinor;
        }

        public BuildVersion(BuildVersion copy)
        {
            Major = copy.Major;
            Minor = copy.Minor;
        }

        public int Compare(BuildVersion other)
        {
            if(other.Major == Major)
            {
                return Minor - other.Minor;
            }
            return Major - other.Major;
        }

        public override string ToString()
        {
            return Decimal;
        }
        public string Hex
        {
            get
            {
                return string.Format("{0}.{1}", Major.ToString("x"), Minor.ToString("x"));
            }
        }

        public string Decimal
        {
            get { return string.Format("{0}.{1}", Major, Minor); }
        }

        public static BuildVersion Default
        {
            get { return new BuildVersion(1,0); }
        }

        public override bool Equals(object obj)
        {
            return Compare(obj as BuildVersion) == 0;
        }
        public override int GetHashCode()
        {
            return (Major + Minor.ToString()).GetHashCode();
        }
        public void Set(BuildVersion rf)
        {
            Major = rf.Major;
            Minor = rf.Minor;
        }

        public static BuildVersion FromFile(string file)
        {
            try
            {
                var ver = FileVersionInfo.GetVersionInfo(file);
                return new BuildVersion(ver.ProductMajorPart, ver.ProductMinorPart);
            }
            catch(InvalidOperationException)
            {
                return new BuildVersion(0,0);
            }
        }

        public static void ToInt(string version, ref uint ms, ref uint ls)
        {
            try
            {
                var spl = version.Split('.');
                ls = 0;
                ms = (uint) (ushort.Parse(spl[0]) << 16);
                if (spl.Length > 1)
                    ms += ushort.Parse(spl[1]);

                if (spl.Length > 2)
                    ls = (uint) (ushort.Parse(spl[2]) << 16);
                if (spl.Length > 3)
                    ls += ushort.Parse(spl[3]);
            }
            catch
            {
                throw new Exception("Version is not in correct format:" + version);
            }
        }
        public class VersionComparer: IComparer<BuildVersion>
        {
            public int Compare(BuildVersion x, BuildVersion y)
            {
                return x.Compare(y);
            }
        }
    }
}